package main

import (
	"fmt"
	"jvm/nzpJvm/instructions"
	"jvm/nzpJvm/instructions/base"
	"jvm/nzpJvm/runtime_area"
	"jvm/nzpJvm/runtime_area/heap"
)

// 字节码解释器
func interpret(method *heap.Method, args []string) {

	thread := runtime_area.NewThread()
	frame := thread.NewFrame(method)
	thread.PushFrame(frame)

	javaArgs := createArgsArray(method.Class().Loader(), args)

	// 将main方法的参数设置在局部变量表的第一个位置
	frame.LocalVars().SetRef(0,javaArgs)

	Loop(thread)
}

func createArgsArray(loader *heap.ClassLoader, args []string) *heap.Object {
	stringClass := loader.LoadClass("java/lang/String")
	stringArrayClass:= stringClass.ArrayClass()
	// java中String类型的对象
	stringArrayObject := stringArrayClass.NewArray(uint(len(args)))
	javaArgs := stringArrayObject.Refs()
	for i,arg := range args {
		javaArgs[i]=heap.JavaString(loader,arg)
	}
	return stringArrayObject
}

func Loop(thread *runtime_area.Thread) {
	reader := &base.BytecodeReader{} // 从code属性中读取字节码

	for {
		frame := thread.CurrentFrame()
		pc := frame.NextPC()
		thread.SetPC(pc)

		reader.Reset(frame.Method().Code(), pc)
		opCode := reader.ReadUint8()
		instruction := instructions.NewInstruction(opCode)

		instruction.FetchOperands(reader) // 从字节码中获取操作数
		frame.SetNextPc(reader.PC())      // PC计数器指向下一条指令的位置，或跳过操作数部分的字节码
		instruction.Execute(frame)        // 执行指令

		// 线程栈为空，意思是main方法都已经退出了，程序现在可以停止运行
		if thread.IsStackEmpty() {
			fmt.Println("运行结束")
			break
		}
	}
}
